package nl.weeaboo.sh.model;

import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import timon.common.xml.XmlElement;

public class AreaModel {

	private String id;
	private Map<String, TileSetModel> tileSets;
	private List<RoomModel> rooms;
	private Rectangle spriteBounds;

	public AreaModel(String id) {
		this.id = id;		
		this.tileSets = new HashMap<String, TileSetModel>();
		this.rooms = new ArrayList<RoomModel>();
		this.spriteBounds = new Rectangle();
	}
	
	//Functions
	public String generateRoomId() {
		String id;
		int t = 0;
		
		do {
			t++;
			id = "room" + t;
		} while (getRoom(id) != null);
		
		return id;
	}
	
	public void addRoom(RoomModel room) {
		rooms.add(room);
		recalculateSpriteBounds();
	}
	public void removeRoom(RoomModel room) {
		rooms.remove(room);
		recalculateSpriteBounds();
	}
	
	public void addTileSet(TileSetModel ts) {
		tileSets.put(ts.getId(), ts);
	}
	
	protected void recalculateSpriteBounds() {
		int minX =  1000000;
		int maxX = -1000000;
		int minY =  1000000;
		int maxY = -1000000;
		
		for (RoomModel r : rooms) {
			minX = Math.min(minX, r.getX());
			maxX = Math.max(maxX, r.getX()+r.getWidth()-1);
			minY = Math.min(minY, r.getY()); 
			maxY = Math.max(maxY, r.getY()+r.getHeight()-1);
		}
		
		minY = -1000000; //Can't exit level on the top
		int r = 25;
		spriteBounds = new Rectangle(minX-r, minY-r, maxX-minX+1+r+r, maxY-minY+1+r+r);
	}
	
	//Getters
	public String getId() { return id; }
	public List<RoomModel> getRooms() { return rooms; }
	public RoomModel getRoom(int x, int y) {
		for (RoomModel room : rooms) {
			if (room.contains(x, y)) return room;
		}
		return null;
	}
	public TileSetIndex getTile(int layer, int x, int y) {
		RoomModel room = getRoom(x, y);
		if (room != null) {
			return room.getTile(layer, new Point(x - room.getX(), y - room.getY()));
		}
		return null;
	}
	public RoomEnemyModel getEnemy(int x, int y) {
		RoomModel room = getRoom(x, y);
		if (room != null) {
			return room.getEnemy(new Point(x - room.getX(), y - room.getY()));
		}
		return null;
	}
	public TileSetModel getTileSet(String id) {
		return tileSets.get(id);
	}
	public Map<String, TileSetModel> getTileSets() {
		return tileSets;
	}
	public RoomModel getRoom(String id) {
		for (RoomModel r : rooms) {
			if (id.equals(r.getId())) return r;
		}
		return null;
	}
	public Rectangle getSpriteBounds() { return spriteBounds; }
	
	//Setters
	public void setTile(int layer, int x, int y, TileSetIndex index) throws IllegalArgumentException {
		RoomModel room = getRoom(x, y);
		if (room == null) throw new IllegalArgumentException("Location is outside all rooms: (" + x + ", " + y + ")");
		room.setTile(layer, x - room.getX(), y - room.getY(), index);
	}
	public void setEnemy(int x, int y, RoomEnemyModel enemy) throws IllegalArgumentException {
		RoomModel room = getRoom(x, y);
		if (room == null) throw new IllegalArgumentException("Location is outside all rooms: (" + x + ", " + y + ")");
		room.setRoomEnemy(x - room.getX(), y - room.getY(), enemy);
	}
	
	//Save Support
	public XmlElement save() {
		XmlElement rootE = new XmlElement("area");
		rootE.addAttribute("version", "1.0.0");
		rootE.addAttribute("id", id);
		
		XmlElement tileSetsE = rootE.addChild("tileSets");
		for (TileSetModel tsm : tileSets.values()) {
			tileSetsE.addChild("tileSet", tsm.getId());
		}
		
		for (RoomModel rm : rooms) {
			rm.save(rootE);
		}
		
		return rootE;
	}
	
}
